package com.gframework.lang;

/**
 * 用于存储一个<strong>正数</strong>索引范围的类.
 * 如果start和end任意一个是负数，则表示没有找到指定数据的索引范围。
 * <p>
 * 代码来自javafx包中的IndexRange
 * </p>
 * 
 * @since 1.0.0
 * @author Ghwolf
 */
public class IndexRange {
	/**
	 * 这是一个可以用于表示没有找到范围的IndexRange对象，他是不可变的，且{@link #IndexRange(int, int)}永恒返回false
	 */
	public static final IndexRange NON_RANGE = new IndexRange(0,0){
		@Override
		public boolean hasRange() {return false;}
		@Override
		public int getLength() {return 0;}
		@Override
		public int getEnd() {return -1;}
		@Override
		public int getStart() {return -1;}
	};

	private int start;
	private int end;

	/**
	 * Index range value delimiter.
	 */
	public static final String VALUE_DELIMITER = ",";

	/**
	 * Creates an instance of IndexRange representing the range between
	 * <code>start</code> and <code>end</code>.
	 *
	 * @param start The start position of the range.
	 * @param end The end position of the range.
	 */
	public IndexRange(int start, int end) {
		if (end < start) {
			throw new IllegalArgumentException();
		}

		this.start = start;
		this.end = end;
	}

	/**
	 * Returns the start position of the range.
	 */
	public int getStart() {
		return start;
	}

	/**
	 * Returns the end position of the range (exclusive).
	 */
	public int getEnd() {
		return end;
	}

	/**
	 * Returns the length of the range.
	 */
	public int getLength() {
		return end - start;
	}
	
	/**
	 * 判断是否存在范围，通常可以用他来判断是否找到特定的数据.
	 * 例如一个字符串中寻找一个开头和结尾的标记，用此方法可以判断是否找到既存在这样的标记。
	 * 
	 * @return true表示存在范围，false表示没有指定任何范围
	 */
	public boolean hasRange() {
		return this.start >= 0 && this.end >= 0 ;
	}

	/**
	 * Indicates whether some other object is "equal to" this one.
	 * 
	 * @param object the reference object with which to compare.
	 * @return {@code true} if this object is equal to the {@code object}
	 *         argument; {@code false} otherwise.
	 */
	@Override
	public boolean equals(Object object) {
		if (object == this) return true;
		if (object instanceof IndexRange) {
			IndexRange range = (IndexRange) object;
			return (start == range.start && end == range.end);
		}

		return false;
	}

	/**
	 * Returns a hash code for this {@code Range} object.
	 * 
	 * @return a hash code for this {@code Range} object.
	 */
	@Override
	public int hashCode() {
		return 31 * start + end;
	}

	/**
	 * Returns a string representation of this {@code Range} object.
	 * 
	 * @return a string representation of this {@code Range} object.
	 */
	@Override
	public String toString() {
		return start + VALUE_DELIMITER + " " + end;
	}
}
